{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "tf_serving.ipynb",
      "provenance": [],
      "toc_visible": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    }
  },
  "cells": [
    {
      "cell_type": "code",
      "metadata": {
        "id": "LfE9rPpSopCG",
        "outputId": "2785ed71-b109-4cb0-987f-59fa4e42cc4b",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "%tensorflow_version 2.x\n",
        "import tensorflow as tf\n",
        "print(tf.__version__)\n",
        "from tensorflow.keras import * "
      ],
      "execution_count": 1,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "2.3.0\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Np5LVhKhZE9-"
      },
      "source": [
        "# Helper libraries\n",
        "import numpy as np\n",
        "import matplotlib.pyplot as plt\n",
        "import os\n",
        "import subprocess\n"
      ],
      "execution_count": 2,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "zp5KP5IUGpc5"
      },
      "source": [
        "# 生成 pb 模型文件"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "3Cgz7l6vZE7H",
        "outputId": "d56461a1-8422-46bc-d207-c62669807140",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "from tensorflow.keras import models,layers,optimizers\n",
        "\n",
        "## 样本数量\n",
        "n = 800\n",
        "\n",
        "## 生成测试用数据集\n",
        "X = tf.random.uniform([n,2],minval=-10,maxval=10) \n",
        "w0 = tf.constant([[2.0],[-1.0]])\n",
        "b0 = tf.constant(3.0)\n",
        "\n",
        "Y = X@w0 + b0 + tf.random.normal([n,1],mean = 0.0,stddev= 2.0)  # @表示矩阵乘法,增加正态扰动\n",
        "\n",
        "## 建立模型\n",
        "tf.keras.backend.clear_session()\n",
        "inputs = layers.Input(shape = (2,),name =\"inputs\") # 设置输入名字为inputs\n",
        "outputs = layers.Dense(1, name = \"outputs\")(inputs) # 设置输出名字为outputs\n",
        "linear = models.Model(inputs = inputs,outputs = outputs)\n",
        "linear.summary()\n",
        "\n",
        "## 使用fit方法进行训练\n",
        "linear.compile(optimizer=\"rmsprop\",loss=\"mse\",metrics=[\"mae\"])\n",
        "linear.fit(X,Y,batch_size = 8,epochs = 100)  \n",
        "\n",
        "tf.print(\"w = \",linear.layers[1].kernel)\n",
        "tf.print(\"b = \",linear.layers[1].bias)\n",
        "\n",
        "## 将模型保存成pb格式文件\n",
        "export_path = \"./data/linear_model/\"\n",
        "version = \"1\"       #后续可以通过版本号进行模型版本迭代与管理\n",
        "linear.save(export_path+version, save_format=\"tf\") \n"
      ],
      "execution_count": 3,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Model: \"functional_1\"\n",
            "_________________________________________________________________\n",
            "Layer (type)                 Output Shape              Param #   \n",
            "=================================================================\n",
            "inputs (InputLayer)          [(None, 2)]               0         \n",
            "_________________________________________________________________\n",
            "outputs (Dense)              (None, 1)                 3         \n",
            "=================================================================\n",
            "Total params: 3\n",
            "Trainable params: 3\n",
            "Non-trainable params: 0\n",
            "_________________________________________________________________\n",
            "Epoch 1/100\n",
            "100/100 [==============================] - 0s 767us/step - loss: 299.2545 - mae: 14.8298\n",
            "Epoch 2/100\n",
            "100/100 [==============================] - 0s 762us/step - loss: 279.6935 - mae: 14.3364\n",
            "Epoch 3/100\n",
            "100/100 [==============================] - 0s 730us/step - loss: 260.9466 - mae: 13.8453\n",
            "Epoch 4/100\n",
            "100/100 [==============================] - 0s 756us/step - loss: 242.4163 - mae: 13.3536\n",
            "Epoch 5/100\n",
            "100/100 [==============================] - 0s 805us/step - loss: 225.7285 - mae: 12.8778\n",
            "Epoch 6/100\n",
            "100/100 [==============================] - 0s 808us/step - loss: 209.0746 - mae: 12.3925\n",
            "Epoch 7/100\n",
            "100/100 [==============================] - 0s 754us/step - loss: 193.0840 - mae: 11.9075\n",
            "Epoch 8/100\n",
            "100/100 [==============================] - 0s 751us/step - loss: 177.9745 - mae: 11.4279\n",
            "Epoch 9/100\n",
            "100/100 [==============================] - 0s 803us/step - loss: 163.2228 - mae: 10.9433\n",
            "Epoch 10/100\n",
            "100/100 [==============================] - 0s 738us/step - loss: 149.5750 - mae: 10.4677\n",
            "Epoch 11/100\n",
            "100/100 [==============================] - 0s 781us/step - loss: 136.1686 - mae: 9.9827\n",
            "Epoch 12/100\n",
            "100/100 [==============================] - 0s 755us/step - loss: 123.5378 - mae: 9.5062\n",
            "Epoch 13/100\n",
            "100/100 [==============================] - 0s 742us/step - loss: 111.9528 - mae: 9.0369\n",
            "Epoch 14/100\n",
            "100/100 [==============================] - 0s 729us/step - loss: 100.5817 - mae: 8.5639\n",
            "Epoch 15/100\n",
            "100/100 [==============================] - 0s 753us/step - loss: 89.9643 - mae: 8.0892\n",
            "Epoch 16/100\n",
            "100/100 [==============================] - 0s 790us/step - loss: 79.9226 - mae: 7.6170\n",
            "Epoch 17/100\n",
            "100/100 [==============================] - 0s 758us/step - loss: 70.5777 - mae: 7.1516\n",
            "Epoch 18/100\n",
            "100/100 [==============================] - 0s 721us/step - loss: 62.0565 - mae: 6.6889\n",
            "Epoch 19/100\n",
            "100/100 [==============================] - 0s 756us/step - loss: 53.7888 - mae: 6.2193\n",
            "Epoch 20/100\n",
            "100/100 [==============================] - 0s 736us/step - loss: 46.4748 - mae: 5.7633\n",
            "Epoch 21/100\n",
            "100/100 [==============================] - 0s 722us/step - loss: 39.6561 - mae: 5.3043\n",
            "Epoch 22/100\n",
            "100/100 [==============================] - 0s 884us/step - loss: 33.5358 - mae: 4.8526\n",
            "Epoch 23/100\n",
            "100/100 [==============================] - 0s 759us/step - loss: 28.0190 - mae: 4.4166\n",
            "Epoch 24/100\n",
            "100/100 [==============================] - 0s 750us/step - loss: 23.2681 - mae: 4.0033\n",
            "Epoch 25/100\n",
            "100/100 [==============================] - 0s 759us/step - loss: 18.8967 - mae: 3.5897\n",
            "Epoch 26/100\n",
            "100/100 [==============================] - 0s 769us/step - loss: 15.3223 - mae: 3.2077\n",
            "Epoch 27/100\n",
            "100/100 [==============================] - 0s 815us/step - loss: 12.3336 - mae: 2.8626\n",
            "Epoch 28/100\n",
            "100/100 [==============================] - 0s 753us/step - loss: 9.9181 - mae: 2.5508\n",
            "Epoch 29/100\n",
            "100/100 [==============================] - 0s 735us/step - loss: 8.0346 - mae: 2.2981\n",
            "Epoch 30/100\n",
            "100/100 [==============================] - 0s 784us/step - loss: 6.8231 - mae: 2.1046\n",
            "Epoch 31/100\n",
            "100/100 [==============================] - 0s 770us/step - loss: 5.9991 - mae: 1.9708\n",
            "Epoch 32/100\n",
            "100/100 [==============================] - 0s 781us/step - loss: 5.5401 - mae: 1.8885\n",
            "Epoch 33/100\n",
            "100/100 [==============================] - 0s 725us/step - loss: 5.2690 - mae: 1.8356\n",
            "Epoch 34/100\n",
            "100/100 [==============================] - 0s 873us/step - loss: 5.0670 - mae: 1.7956\n",
            "Epoch 35/100\n",
            "100/100 [==============================] - 0s 821us/step - loss: 4.8981 - mae: 1.7599\n",
            "Epoch 36/100\n",
            "100/100 [==============================] - 0s 761us/step - loss: 4.7446 - mae: 1.7309\n",
            "Epoch 37/100\n",
            "100/100 [==============================] - 0s 732us/step - loss: 4.6193 - mae: 1.7074\n",
            "Epoch 38/100\n",
            "100/100 [==============================] - 0s 714us/step - loss: 4.5073 - mae: 1.6860\n",
            "Epoch 39/100\n",
            "100/100 [==============================] - 0s 766us/step - loss: 4.4036 - mae: 1.6683\n",
            "Epoch 40/100\n",
            "100/100 [==============================] - 0s 745us/step - loss: 4.3108 - mae: 1.6502\n",
            "Epoch 41/100\n",
            "100/100 [==============================] - 0s 753us/step - loss: 4.2425 - mae: 1.6397\n",
            "Epoch 42/100\n",
            "100/100 [==============================] - 0s 854us/step - loss: 4.1834 - mae: 1.6288\n",
            "Epoch 43/100\n",
            "100/100 [==============================] - 0s 751us/step - loss: 4.1319 - mae: 1.6180\n",
            "Epoch 44/100\n",
            "100/100 [==============================] - 0s 715us/step - loss: 4.0909 - mae: 1.6128\n",
            "Epoch 45/100\n",
            "100/100 [==============================] - 0s 730us/step - loss: 4.0590 - mae: 1.6079\n",
            "Epoch 46/100\n",
            "100/100 [==============================] - 0s 759us/step - loss: 4.0326 - mae: 1.6029\n",
            "Epoch 47/100\n",
            "100/100 [==============================] - 0s 705us/step - loss: 4.0116 - mae: 1.6001\n",
            "Epoch 48/100\n",
            "100/100 [==============================] - 0s 767us/step - loss: 3.9939 - mae: 1.5967\n",
            "Epoch 49/100\n",
            "100/100 [==============================] - 0s 774us/step - loss: 3.9808 - mae: 1.5941\n",
            "Epoch 50/100\n",
            "100/100 [==============================] - 0s 786us/step - loss: 3.9692 - mae: 1.5947\n",
            "Epoch 51/100\n",
            "100/100 [==============================] - 0s 789us/step - loss: 3.9617 - mae: 1.5941\n",
            "Epoch 52/100\n",
            "100/100 [==============================] - 0s 749us/step - loss: 3.9569 - mae: 1.5904\n",
            "Epoch 53/100\n",
            "100/100 [==============================] - 0s 891us/step - loss: 3.9523 - mae: 1.5910\n",
            "Epoch 54/100\n",
            "100/100 [==============================] - 0s 913us/step - loss: 3.9493 - mae: 1.5916\n",
            "Epoch 55/100\n",
            "100/100 [==============================] - 0s 797us/step - loss: 3.9460 - mae: 1.5922\n",
            "Epoch 56/100\n",
            "100/100 [==============================] - 0s 751us/step - loss: 3.9449 - mae: 1.5909\n",
            "Epoch 57/100\n",
            "100/100 [==============================] - 0s 870us/step - loss: 3.9430 - mae: 1.5903\n",
            "Epoch 58/100\n",
            "100/100 [==============================] - 0s 776us/step - loss: 3.9418 - mae: 1.5903\n",
            "Epoch 59/100\n",
            "100/100 [==============================] - 0s 832us/step - loss: 3.9380 - mae: 1.5916\n",
            "Epoch 60/100\n",
            "100/100 [==============================] - 0s 745us/step - loss: 3.9405 - mae: 1.5905\n",
            "Epoch 61/100\n",
            "100/100 [==============================] - 0s 770us/step - loss: 3.9388 - mae: 1.5904\n",
            "Epoch 62/100\n",
            "100/100 [==============================] - 0s 828us/step - loss: 3.9373 - mae: 1.5903\n",
            "Epoch 63/100\n",
            "100/100 [==============================] - 0s 859us/step - loss: 3.9389 - mae: 1.5909\n",
            "Epoch 64/100\n",
            "100/100 [==============================] - 0s 767us/step - loss: 3.9394 - mae: 1.5922\n",
            "Epoch 65/100\n",
            "100/100 [==============================] - 0s 764us/step - loss: 3.9382 - mae: 1.5927\n",
            "Epoch 66/100\n",
            "100/100 [==============================] - 0s 813us/step - loss: 3.9369 - mae: 1.5914\n",
            "Epoch 67/100\n",
            "100/100 [==============================] - 0s 778us/step - loss: 3.9402 - mae: 1.5913\n",
            "Epoch 68/100\n",
            "100/100 [==============================] - 0s 753us/step - loss: 3.9395 - mae: 1.5913\n",
            "Epoch 69/100\n",
            "100/100 [==============================] - 0s 810us/step - loss: 3.9375 - mae: 1.5906\n",
            "Epoch 70/100\n",
            "100/100 [==============================] - 0s 780us/step - loss: 3.9381 - mae: 1.5919\n",
            "Epoch 71/100\n",
            "100/100 [==============================] - 0s 821us/step - loss: 3.9360 - mae: 1.5918\n",
            "Epoch 72/100\n",
            "100/100 [==============================] - 0s 768us/step - loss: 3.9383 - mae: 1.5909\n",
            "Epoch 73/100\n",
            "100/100 [==============================] - 0s 775us/step - loss: 3.9386 - mae: 1.5912\n",
            "Epoch 74/100\n",
            "100/100 [==============================] - 0s 789us/step - loss: 3.9391 - mae: 1.5918\n",
            "Epoch 75/100\n",
            "100/100 [==============================] - 0s 822us/step - loss: 3.9389 - mae: 1.5914\n",
            "Epoch 76/100\n",
            "100/100 [==============================] - 0s 843us/step - loss: 3.9382 - mae: 1.5912\n",
            "Epoch 77/100\n",
            "100/100 [==============================] - 0s 799us/step - loss: 3.9386 - mae: 1.5919\n",
            "Epoch 78/100\n",
            "100/100 [==============================] - 0s 815us/step - loss: 3.9379 - mae: 1.5915\n",
            "Epoch 79/100\n",
            "100/100 [==============================] - 0s 742us/step - loss: 3.9378 - mae: 1.5909\n",
            "Epoch 80/100\n",
            "100/100 [==============================] - 0s 702us/step - loss: 3.9368 - mae: 1.5918\n",
            "Epoch 81/100\n",
            "100/100 [==============================] - 0s 844us/step - loss: 3.9362 - mae: 1.5915\n",
            "Epoch 82/100\n",
            "100/100 [==============================] - 0s 746us/step - loss: 3.9391 - mae: 1.5906\n",
            "Epoch 83/100\n",
            "100/100 [==============================] - 0s 741us/step - loss: 3.9378 - mae: 1.5909\n",
            "Epoch 84/100\n",
            "100/100 [==============================] - 0s 786us/step - loss: 3.9381 - mae: 1.5917\n",
            "Epoch 85/100\n",
            "100/100 [==============================] - 0s 722us/step - loss: 3.9369 - mae: 1.5918\n",
            "Epoch 86/100\n",
            "100/100 [==============================] - 0s 746us/step - loss: 3.9377 - mae: 1.5913\n",
            "Epoch 87/100\n",
            "100/100 [==============================] - 0s 807us/step - loss: 3.9361 - mae: 1.5908\n",
            "Epoch 88/100\n",
            "100/100 [==============================] - 0s 739us/step - loss: 3.9388 - mae: 1.5919\n",
            "Epoch 89/100\n",
            "100/100 [==============================] - 0s 746us/step - loss: 3.9380 - mae: 1.5912\n",
            "Epoch 90/100\n",
            "100/100 [==============================] - 0s 804us/step - loss: 3.9378 - mae: 1.5912\n",
            "Epoch 91/100\n",
            "100/100 [==============================] - 0s 859us/step - loss: 3.9373 - mae: 1.5919\n",
            "Epoch 92/100\n",
            "100/100 [==============================] - 0s 874us/step - loss: 3.9356 - mae: 1.5911\n",
            "Epoch 93/100\n",
            "100/100 [==============================] - 0s 744us/step - loss: 3.9393 - mae: 1.5928\n",
            "Epoch 94/100\n",
            "100/100 [==============================] - 0s 742us/step - loss: 3.9366 - mae: 1.5924\n",
            "Epoch 95/100\n",
            "100/100 [==============================] - 0s 778us/step - loss: 3.9381 - mae: 1.5913\n",
            "Epoch 96/100\n",
            "100/100 [==============================] - 0s 754us/step - loss: 3.9377 - mae: 1.5918\n",
            "Epoch 97/100\n",
            "100/100 [==============================] - 0s 780us/step - loss: 3.9394 - mae: 1.5914\n",
            "Epoch 98/100\n",
            "100/100 [==============================] - 0s 771us/step - loss: 3.9372 - mae: 1.5919\n",
            "Epoch 99/100\n",
            "100/100 [==============================] - 0s 754us/step - loss: 3.9385 - mae: 1.5905\n",
            "Epoch 100/100\n",
            "100/100 [==============================] - 0s 807us/step - loss: 3.9384 - mae: 1.5930\n",
            "w =  [[1.98877275]\n",
            " [-0.988767147]]\n",
            "b =  [3.05564809]\n",
            "WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/training/tracking/tracking.py:111: Model.state_updates (from tensorflow.python.keras.engine.training) is deprecated and will be removed in a future version.\n",
            "Instructions for updating:\n",
            "This property should not be used in TensorFlow 2.0, as updates are applied automatically.\n",
            "WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/training/tracking/tracking.py:111: Layer.updates (from tensorflow.python.keras.engine.base_layer) is deprecated and will be removed in a future version.\n",
            "Instructions for updating:\n",
            "This property should not be used in TensorFlow 2.0, as updates are applied automatically.\n",
            "INFO:tensorflow:Assets written to: ./data/linear_model/1/assets\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "3brFeTw5ZE3i",
        "outputId": "65625b99-38c0-4767-a25b-4544891c6cf6",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "# 查看保存的模型文件\n",
        "!ls {export_path+version}"
      ],
      "execution_count": 5,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "assets\tsaved_model.pb\tvariables\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "3eY2GOLSZE1H",
        "outputId": "03979b2e-cbec-4176-f839-8959af000fcc",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "# 查看模型文件相关信息\n",
        "!saved_model_cli show --dir {export_path+str(version)} --all"
      ],
      "execution_count": 6,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "\n",
            "MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs:\n",
            "\n",
            "signature_def['__saved_model_init_op']:\n",
            "  The given SavedModel SignatureDef contains the following input(s):\n",
            "  The given SavedModel SignatureDef contains the following output(s):\n",
            "    outputs['__saved_model_init_op'] tensor_info:\n",
            "        dtype: DT_INVALID\n",
            "        shape: unknown_rank\n",
            "        name: NoOp\n",
            "  Method name is: \n",
            "\n",
            "signature_def['serving_default']:\n",
            "  The given SavedModel SignatureDef contains the following input(s):\n",
            "    inputs['inputs'] tensor_info:\n",
            "        dtype: DT_FLOAT\n",
            "        shape: (-1, 2)\n",
            "        name: serving_default_inputs:0\n",
            "  The given SavedModel SignatureDef contains the following output(s):\n",
            "    outputs['outputs'] tensor_info:\n",
            "        dtype: DT_FLOAT\n",
            "        shape: (-1, 1)\n",
            "        name: StatefulPartitionedCall:0\n",
            "  Method name is: tensorflow/serving/predict\n",
            "WARNING: Logging before flag parsing goes to stderr.\n",
            "W1007 02:46:15.128861 140184870020992 deprecation.py:506] From /usr/local/lib/python2.7/dist-packages/tensorflow_core/python/ops/resource_variable_ops.py:1786: calling __init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.\n",
            "Instructions for updating:\n",
            "If using Keras pass *_constraint arguments to layers.\n",
            "\n",
            "Defined Functions:\n",
            "  Function Name: '__call__'\n",
            "    Option #1\n",
            "      Callable with:\n",
            "        Argument #1\n",
            "          inputs: TensorSpec(shape=(None, 2), dtype=tf.float32, name=u'inputs')\n",
            "        Argument #2\n",
            "          DType: bool\n",
            "          Value: True\n",
            "        Argument #3\n",
            "          DType: NoneType\n",
            "          Value: None\n",
            "    Option #2\n",
            "      Callable with:\n",
            "        Argument #1\n",
            "          inputs: TensorSpec(shape=(None, 2), dtype=tf.float32, name=u'inputs')\n",
            "        Argument #2\n",
            "          DType: bool\n",
            "          Value: False\n",
            "        Argument #3\n",
            "          DType: NoneType\n",
            "          Value: None\n",
            "\n",
            "  Function Name: '_default_save_signature'\n",
            "    Option #1\n",
            "      Callable with:\n",
            "        Argument #1\n",
            "          inputs: TensorSpec(shape=(None, 2), dtype=tf.float32, name=u'inputs')\n",
            "\n",
            "  Function Name: 'call_and_return_all_conditional_losses'\n",
            "    Option #1\n",
            "      Callable with:\n",
            "        Argument #1\n",
            "          inputs: TensorSpec(shape=(None, 2), dtype=tf.float32, name=u'inputs')\n",
            "        Argument #2\n",
            "          DType: bool\n",
            "          Value: False\n",
            "        Argument #3\n",
            "          DType: NoneType\n",
            "          Value: None\n",
            "    Option #2\n",
            "      Callable with:\n",
            "        Argument #1\n",
            "          inputs: TensorSpec(shape=(None, 2), dtype=tf.float32, name=u'inputs')\n",
            "        Argument #2\n",
            "          DType: bool\n",
            "          Value: True\n",
            "        Argument #3\n",
            "          DType: NoneType\n",
            "          Value: None\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "FJSyshdpG1r_"
      },
      "source": [
        "# 安装 tf-serving"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "LBPXtH8iZEup",
        "outputId": "04022013-2c1e-4175-ccb6-70ebb1b9d01e",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "!curl https://storage.googleapis.com/tensorflow-serving-apt/tensorflow-serving.release.pub.gpg | apt-key add -"
      ],
      "execution_count": 7,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current\n",
            "                                 Dload  Upload   Total   Spent    Left  Speed\n",
            "\r  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0\r100  2943  100  2943    0     0  28852      0 --:--:-- --:--:-- --:--:-- 28852\n",
            "OK\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "KhciWl7WZEsJ",
        "outputId": "4c2378e9-014b-44f0-da4d-9c2967652243",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "!apt update"
      ],
      "execution_count": 8,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "\u001b[33m\r0% [Working]\u001b[0m\r            \rGet:1 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]\n",
            "\u001b[33m\r0% [Connecting to archive.ubuntu.com (91.189.88.142)] [1 InRelease 0 B/88.7 kB \u001b[0m\r                                                                               \rIgn:2 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64  InRelease\n",
            "\u001b[33m\r0% [Waiting for headers] [1 InRelease 80.8 kB/88.7 kB 91%] [Connected to cloud.\u001b[0m\u001b[33m\r0% [Waiting for headers] [Connected to cloud.r-project.org (99.84.194.50)] [Wai\u001b[0m\u001b[33m\r0% [1 InRelease gpgv 88.7 kB] [Waiting for headers] [Connected to cloud.r-proje\u001b[0m\r                                                                               \rIgn:3 https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64  InRelease\n",
            "\u001b[33m\r0% [1 InRelease gpgv 88.7 kB] [Waiting for headers] [Connected to cloud.r-proje\u001b[0m\r                                                                               \rGet:4 http://ppa.launchpad.net/c2d4u.team/c2d4u4.0+/ubuntu bionic InRelease [15.9 kB]\n",
            "\u001b[33m\r0% [1 InRelease gpgv 88.7 kB] [Waiting for headers] [Connected to cloud.r-proje\u001b[0m\r                                                                               \rHit:5 http://archive.ubuntu.com/ubuntu bionic InRelease\n",
            "\u001b[33m\r0% [1 InRelease gpgv 88.7 kB] [Waiting for headers] [Connected to cloud.r-proje\u001b[0m\r                                                                               \rHit:6 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64  Release\n",
            "Hit:7 https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64  Release\n",
            "Get:8 http://archive.ubuntu.com/ubuntu bionic-updates InRelease [88.7 kB]\n",
            "Get:9 https://cloud.r-project.org/bin/linux/ubuntu bionic-cran40/ InRelease [3,626 B]\n",
            "Get:10 http://security.ubuntu.com/ubuntu bionic-security/main amd64 Packages [1,693 kB]\n",
            "Hit:11 http://ppa.launchpad.net/graphics-drivers/ppa/ubuntu bionic InRelease\n",
            "Get:12 http://security.ubuntu.com/ubuntu bionic-security/universe amd64 Packages [1,340 kB]\n",
            "Get:13 http://archive.ubuntu.com/ubuntu bionic-backports InRelease [74.6 kB]\n",
            "Get:16 http://ppa.launchpad.net/c2d4u.team/c2d4u4.0+/ubuntu bionic/main Sources [1,675 kB]\n",
            "Get:17 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 Packages [2,104 kB]\n",
            "Get:18 http://ppa.launchpad.net/c2d4u.team/c2d4u4.0+/ubuntu bionic/main amd64 Packages [857 kB]\n",
            "Get:19 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 Packages [2,110 kB]\n",
            "Fetched 10.1 MB in 3s (3,540 kB/s)\n",
            "Reading package lists... Done\n",
            "Building dependency tree       \n",
            "Reading state information... Done\n",
            "8 packages can be upgraded. Run 'apt list --upgradable' to see them.\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "t9p99r2rB0PR",
        "outputId": "23e9c499-b3c7-484b-fb85-04dbdaaae6d2",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "!echo \"deb http://storage.googleapis.com/tensorflow-serving-apt stable tensorflow-model-server tensorflow-model-server-universal\" | tee /etc/apt/sources.list.d/tensorflow-serving.list && \\\n",
        "curl https://storage.googleapis.com/tensorflow-serving-apt/tensorflow-serving.release.pub.gpg | apt-key add -\n",
        "!apt update"
      ],
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "deb http://storage.googleapis.com/tensorflow-serving-apt stable tensorflow-model-server tensorflow-model-server-universal\n",
            "  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current\n",
            "                                 Dload  Upload   Total   Spent    Left  Speed\n",
            "\r  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0\r100  2943  100  2943    0     0    99k      0 --:--:-- --:--:-- --:--:--   99k\n",
            "OK\n",
            "Hit:1 http://security.ubuntu.com/ubuntu bionic-security InRelease\n",
            "Ign:2 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64  InRelease\n",
            "Hit:3 https://cloud.r-project.org/bin/linux/ubuntu bionic-cran40/ InRelease\n",
            "Get:4 http://storage.googleapis.com/tensorflow-serving-apt stable InRelease [3,012 B]\n",
            "Ign:5 https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64  InRelease\n",
            "Hit:6 http://ppa.launchpad.net/c2d4u.team/c2d4u4.0+/ubuntu bionic InRelease\n",
            "Hit:7 https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64  Release\n",
            "Hit:8 https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64  Release\n",
            "Hit:9 http://archive.ubuntu.com/ubuntu bionic InRelease\n",
            "Hit:10 http://archive.ubuntu.com/ubuntu bionic-updates InRelease\n",
            "Hit:11 http://ppa.launchpad.net/graphics-drivers/ppa/ubuntu bionic InRelease\n",
            "Hit:12 http://archive.ubuntu.com/ubuntu bionic-backports InRelease\n",
            "Get:13 http://storage.googleapis.com/tensorflow-serving-apt stable/tensorflow-model-server amd64 Packages [341 B]\n",
            "Get:14 http://storage.googleapis.com/tensorflow-serving-apt stable/tensorflow-model-server-universal amd64 Packages [349 B]\n",
            "Fetched 3,702 B in 2s (2,030 B/s)\n",
            "Reading package lists... Done\n",
            "Building dependency tree       \n",
            "Reading state information... Done\n",
            "8 packages can be upgraded. Run 'apt list --upgradable' to see them.\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "uGvJaa6FZEoH",
        "outputId": "eac8a495-8cc4-4877-f957-8494336fc2f1",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "!apt-get install tensorflow-model-server"
      ],
      "execution_count": 10,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Reading package lists... Done\n",
            "Building dependency tree       \n",
            "Reading state information... Done\n",
            "The following NEW packages will be installed:\n",
            "  tensorflow-model-server\n",
            "0 upgraded, 1 newly installed, 0 to remove and 8 not upgraded.\n",
            "Need to get 210 MB of archives.\n",
            "After this operation, 0 B of additional disk space will be used.\n",
            "Get:1 http://storage.googleapis.com/tensorflow-serving-apt stable/tensorflow-model-server amd64 tensorflow-model-server all 2.3.0 [210 MB]\n",
            "Fetched 210 MB in 3s (69.7 MB/s)\n",
            "Selecting previously unselected package tensorflow-model-server.\n",
            "(Reading database ... 144617 files and directories currently installed.)\n",
            "Preparing to unpack .../tensorflow-model-server_2.3.0_all.deb ...\n",
            "Unpacking tensorflow-model-server (2.3.0) ...\n",
            "Setting up tensorflow-model-server (2.3.0) ...\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Dd0_IYd-G80k"
      },
      "source": [
        "# 启动 tf-serving"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "t5v4PH2lCuhE"
      },
      "source": [
        "import os\n",
        "os.environ[\"MODEL_DIR\"] = \"/content/data/linear_model/\""
      ],
      "execution_count": 11,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "rJsm_s7FC65S",
        "outputId": "148e9802-92ec-4a60-ea6e-99c655b62fac",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        }
      },
      "source": [
        "os.environ[\"MODEL_DIR\"]"
      ],
      "execution_count": 12,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "application/vnd.google.colaboratory.intrinsic+json": {
              "type": "string"
            },
            "text/plain": [
              "'/content/data/linear_model/'"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 12
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "wKzijKLqE4XA",
        "outputId": "f5ca1bc5-7e18-4fb3-d62d-aadd7ab31eb8",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "!ls /content/data/linear_model/"
      ],
      "execution_count": 13,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "1\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "D0GXPNVhZEeh",
        "outputId": "53950423-d063-454b-e728-4396848fc30d",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "%%bash --bg \n",
        "nohup tensorflow_model_server \\\n",
        "  --rest_api_port=8501 \\\n",
        "  --model_name=linear_model \\\n",
        "  --model_base_path=\"${MODEL_DIR}\" >server.log 2>&1"
      ],
      "execution_count": 14,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Starting job # 0 in a separate thread.\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Q0HQSvAzErfe",
        "outputId": "e4f8485e-8778-463c-c6be-63a9583e8f0a",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "# 查看日志，有可能会有报错信息\n",
        "!tail server.log"
      ],
      "execution_count": 15,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n",
            "2020-10-07 02:47:13.054328: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:199] Restoring SavedModel bundle.\n",
            "2020-10-07 02:47:13.070400: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:183] Running initialization op on SavedModel bundle at path: /content/data/linear_model/1\n",
            "2020-10-07 02:47:13.072834: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:303] SavedModel load for tags { serve }; Status: success: OK. Took 35625 microseconds.\n",
            "2020-10-07 02:47:13.073239: I tensorflow_serving/servables/tensorflow/saved_model_warmup_util.cc:59] No warmup data file found at /content/data/linear_model/1/assets.extra/tf_serving_warmup_requests\n",
            "2020-10-07 02:47:13.073408: I tensorflow_serving/core/loader_harness.cc:87] Successfully loaded servable version {name: linear_model version: 1}\n",
            "2020-10-07 02:47:13.074536: I tensorflow_serving/model_servers/server.cc:367] Running gRPC ModelServer at 0.0.0.0:8500 ...\n",
            "[warn] getaddrinfo: address family for nodename not supported\n",
            "[evhttp_server.cc : 238] NET_LOG: Entering the event loop ...\n",
            "2020-10-07 02:47:13.075371: I tensorflow_serving/model_servers/server.cc:387] Exporting HTTP/REST API at:localhost:8501 ...\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "iMkgpsvgHRTf"
      },
      "source": [
        "# 向服务API发送请求"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "l4v6hQJQJs4P"
      },
      "source": [
        "可以使用任何编程语言的http功能发送请求，下面示范linux的 curl 命令发送请求，以及Python的requests库发送请求。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "35jg0QlRHceS"
      },
      "source": [
        "使用 Linux 的curl命令发送请求 "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "6OHPZc_RB-YA",
        "outputId": "799cc0c0-c1a9-4238-b005-9cba092b7ba8",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "!curl -d '{\"instances\": [[1.0, 2.0], [5.0,8.0]]}' \\\n",
        "    -X POST http://localhost:8501/v1/models/linear_model:predict"
      ],
      "execution_count": 16,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "{\n",
            "    \"predictions\": [[3.06688643], [5.08937454]\n",
            "    ]\n",
            "}"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "xj6l8bwUIV5g"
      },
      "source": [
        "利用 Python request库发送请求"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "k2mSYdJTB-Nv",
        "outputId": "ca890c9a-ac27-4477-fe45-65a2fbbd0436",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "import json\n",
        "data = json.dumps({\"signature_name\": \"serving_default\", \"instances\": [[1.0, 2.0], [5.0,7.0]]})\n",
        "\n",
        "import requests\n",
        "headers = {\"content-type\": \"application/json\"}\n",
        "json_response = requests.post('http://localhost:8501/v1/models/linear_model:predict', data=data, headers=headers)\n",
        "predictions = json.loads(json_response.text)[\"predictions\"]\n",
        "print(predictions)"
      ],
      "execution_count": 17,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "[[3.06688643], [6.07814217]]\n"
          ],
          "name": "stdout"
        }
      ]
    }
  ]
}